package com.asialjim.wechat.spring.message;

import com.asialjim.wechat.aes.AesException;
import com.asialjim.wechat.aes.WXBizMsgCrypt;
import com.asialjim.wechat.aes.XMLParse;
import com.asialjim.wechat.core.bean.WeChatBean;
import com.asialjim.wechat.message.BaseWeChatCallMessage;
import com.asialjim.wechat.message.output.WeChatOutputMessage;
import com.asialjim.wechat.msgcrypt.WxBizMsgCryptService;
import com.asialjim.wechat.pojo.account.WeChatAccount;
import com.asialjim.wechat.wechataccount.WeChatAccountService;
import com.asialjim.wechat.utils.XmlUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
 * <h1><em>ASIAL JIM JAVA DOC</em></h1><hr/>
 * <h2>CLASS DESCRIPTION <i>[ NAME: WxBizMsgCryptServer ]</i></h2><strong>
 * <p> crypt server
 * </strong><p><p><em>Copyright &copy; Asial Jim Co., LTD</em><hr/>
 *
 * @author Asial Jim &nbsp;&nbsp; <span>Email:<a href="mailto:asialjim@hotmail.com">asialjim@hotmail.com</a> &nbsp;&nbsp; <a href="asialjim@qq.com">asialjim@qq.com</a></span>
 * @version 1.0.0
 * @since 2021/3/11   &nbsp;&nbsp; JDK 8
 */
@Data
@Slf4j
@AllArgsConstructor
public class WxBizMsgCryptServiceImpl implements WxBizMsgCryptService,WeChatBean {
    private WeChatAccountService accountServer;

    /**
     * <h3>METHOD DESCRIPTION <i>[ NAME: wxBizMsgCrypt ]</i></h3>
     * 根据微信公众平台账号获取加解密实体
     * @param accountId {@link String account id}
     * @return {@link WXBizMsgCrypt crypt}
     * @author Asial Jim &nbsp;&nbsp;<span>Email:asialjim@hotmail.com &nbsp;&nbsp; asialjim@qq.com</span>
     * @since 2021/3/16 14:58
     */
    public WXBizMsgCrypt wxBizMsgCrypt(String accountId){
        WXBizMsgCrypt crypt = null;
        try {
            WeChatAccount account = accountServer.account(accountId);
            Assert.notNull(account,"获取微信公众平台帐号实体失败");
            crypt = new WXBizMsgCrypt(account.getToken(), account.getEncodingAesKey(), account.getAppId());
        } catch (AesException e) {
            log.error("生成微信消息加解密器出现异常:{}",e.getMessage());
        }
        return crypt;
    }

    /**
     * <h3>METHOD DESCRIPTION <i>[ NAME: decrypt ]</i></h3>
     * 解密腾迅服务器向开发者服务器推送的加密消息
     * @param callMessage {@link BaseWeChatCallMessage call message}
     * @param msgSignature {@link String msg signature}
     * @param timestamp {@link String timestamp}
     * @param nonce {@link String nonce}
     * @return {@link BaseWeChatCallMessage call message was decrypted}
     * @author Asial Jim &nbsp;&nbsp;<span>Email:asialjim@hotmail.com &nbsp;&nbsp; asialjim@qq.com</span>
     * @since 2021/3/16 14:59
     */
    public BaseWeChatCallMessage decrypt(BaseWeChatCallMessage callMessage, String msgSignature, String timestamp, String nonce){
        if (callMessage == null || !StringUtils.hasLength(callMessage.getEncrypt())){return callMessage;}
        try {
            String xml = "<xml><ToUserName><![CDATA[" + callMessage.getToUserName() + "]]></ToUserName><Encrypt><![CDATA[" + callMessage.getEncrypt() + "]]></Encrypt></xml>";
            log.debug("解密前原消息:{}",xml);
            String afterDecrypt = wxBizMsgCrypt(callMessage.getToUserName()).decryptMsg(msgSignature, timestamp, nonce, xml);
            log.debug("解密后原消息:{}",afterDecrypt);
            callMessage = XmlUtils.xml2Object(afterDecrypt, callMessage.getClass());
            log.debug("解密后原消息实体:{}",callMessage.toString());
        } catch (AesException e) {
            log.error("解密错误:{}",e.getMessage());
        }
        return callMessage;
    }

    /**
     * <h3>METHOD DESCRIPTION <i>[ NAME: encrypt ]</i></h3>
     * 加密消息
     * @param outputMessage {@link WeChatOutputMessage out put message}
     * @param account {@link WeChatAccount we chat account}
     * @param encrypt {@link String encrypt}
     * @param signature {@link String signature}
     * @param timestamp {@link String timestamp}
     * @param nonce {@link String nonce}
     * @return {@link String message encrypted}
     * @author Asial Jim &nbsp;&nbsp;<span>Email:asialjim@hotmail.com &nbsp;&nbsp; asialjim@qq.com</span>
     * @since 2021/3/16 15:01
     */
    public String encrypt(WeChatOutputMessage outputMessage, WeChatAccount account, String encrypt, String signature, String timestamp, String nonce){
        log.info("返回加密消息组包，条件:{}",String.format("OutputMessage:%s,account:%s,signature:%s,timestamp:%s,nonce:%s",outputMessage,account,signature,timestamp,nonce));
        String generate = XMLParse.generate(encrypt, signature, timestamp, nonce);
        log.info("返回加密消息组包完成：{}",generate);
        return generate;
    }
}
